from zope.interface import implements

from twisted.internet import reactor, defer
from twisted.application import service
from twisted.plugin import getPlugins

from pyhsrv import interfaces, errors, net, fakenodeservice, actions
from pyhsrv.pollingservice import PollingService, SrvPollService

from pyhsrv.db.types import SPROTOCOLS, NPROTOCOLS

from time import time

action_types = ['mail']

class PyHSrvService(service.MultiService):
    """Handles the allerts, and starts the polling and the fake node service"""

    implements(interfaces.IControllerService)

    def __init__(self, name, db, cfg):
        """This initiates the database, and the name"""
        self.services = []
        self.name = name
        self.db = db
        self.cfg = cfg
        self.nodes = {}
        self.children = {}
        self.servername =  cfg.get('general', 'servername')
        self.actions = {}
        for i in getPlugins(interfaces.IActionPlugin, actions):
            self.actions[i.getName()] = i
            i.configure(self.cfg, self.db)
        
        def askChildren(children):
            for i in getPlugins(interfaces.INetPlugin, net):
                prot = i.getName()
                for c in children:
                    if c.proto >= 10:
                        p = c.proto - 10
                    else:
                        p = c.proto
                    if prot == SPROTOCOLS[p]:
                        srvpoller = SrvPollService(db, self.servername,
                                                   c.server_id)
                        x = i.makeService(srvpoller,
                                          [c.addr, c.port],
                                          c.proto >= 10,
                                          cfg.get('general', 'mysslcert'),
                                          cfg.get('general', 'casslcert'))
                        x.setServiceParent(self)
                        x.startService()
                        self.children[c.name] = [srvpoller, x]
    
        def starter(nodes):
            for i in getPlugins(interfaces.INetPlugin, net):
                prot = i.getName()
                for n in nodes:
                    if n.proto >= 10:
                        p = n.proto -10
                    else:
                        p = n.proto
                    if p == NPROTOCOLS.index(prot):
                        poller = PollingService(db, self.servername, n.node_id)
                        x = i.makeService(poller,
                                          [n.addr, n.port],
                                          n.proto >= 10,
                                          cfg.get('general', 'mysslcert'),
                                          cfg.get('general', 'casslcert'))
                        x.setServiceParent(self)
                        x.startService()
                        self.nodes[n.name] = [poller, x]
        
        d = self.db.getNodes(self.servername, session = True)
        d.addCallback(starter)
        d.addErrback(errors.catchError)
        d = self.db.getChildren(self.servername, session = True)
        d.addCallback(askChildren)
        d.addErrback(errors.catchError)
        
    def parseMsg(self, msg, p_inst):
        cmd, params = msg.split(' ')[0], msg.split(' ')[1:]
        
        if cmd in self.nodes.keys() + self.children.keys():
            if cmd in self.children.keys():
                cmd = params[0]
                params = params[1:]
            alert_type = params[0]
            plug = params[1].split(':')[0]
            item = params[1].split(':')[1]
            value = params[2]
            if alert_type == 'alert_change':
                if plug == 'ipv4addr':
                    self.db.updateNodeAddress(cmd, value, session=True)
            def doAction(acts):
                for method in acts.keys():
                    if str(method) in self.actions.keys():
                        self.actions[method].doAction(int(time()), cmd,
                                    params[1], value, alert_type,
                                    acts[method][0], acts[method][1])
            d = self.db.getActionForAlert(alert_type, cmd, plug, item,
                                      session = True)
            d.addErrback(errors.catchError)
            d.addCallback(doAction)
            return defer.succeed(None)
                
        
        elif cmd == "www#set" and len(params) == 4:
            if params[0] in self.nodes.keys():
                self.nodes[params[0]][0].setProperty(params[1:])
            else:
                return defer.succeed("error: " + msg)
        
        else:
            return defer.succeed("error: " + msg)

    
    def newConnection(self, a, b):
        pass
    
    def closeConnection(self, p_inst):
        pass

